package com.haohan.cloud.scm.common.tools.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import com.haohan.cloud.scm.common.tools.thread.ScmGlobalThreadPool;
import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;

import java.util.List;

/**
 * @author dy
 * @date 2020/3/14
 * 定时任务基础操作
 */
@Slf4j
@NoArgsConstructor
public abstract class BaseScmSchedulingUtil {

    @NonNull
    @Autowired
    protected ScmIncrementUtil scmIncrementUtil;

    /**
     * 任务名称
     */
    @NonNull
    protected String taskName;

    {
        setTaskName();
    }

    /**
     * 任务名称, 子类中设置
     */
    protected abstract void setTaskName();

    /**
     * 加定时任务注解的执行方法, 子类调用beforeProcess方法
     */
    protected abstract void run();

    /**
     * 定时任务执行前处理
     *
     * @param tenantIdList
     * @param cacheSeconds
     * @param cacheKey
     */
    protected void beforeProcess(List<Integer> tenantIdList, int cacheSeconds, String cacheKey) {
        long time = 1000 * RandomUtil.randomInt(1, 60);
        try {
            log.debug("定时任务: {}, sleep {}", taskName, time);
            Thread.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 多服务防止同时执行
        if (scmIncrementUtil.existKey(cacheKey, cacheSeconds)) {
            return;
        }
        // 多租户
        if (CollUtil.isNotEmpty(tenantIdList)) {
            tenantIdList.forEach(tenantId -> {
                TenantContextHolder.setTenantId(tenantId);
                // 防止getUser报错
                SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("admin", "admin"));
                log.debug("定时任务: {}, 租户：{};", taskName, tenantId);
                // 执行任务
                ScmGlobalThreadPool.getExecutor().execute(this::process);
            });
        }
    }

    /**
     * 执行的定时方法 内容
     */
    protected abstract void process();

}
